{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# JavaScript prototype（原型对象）\n",
    "所有的 JavaScript 对象都会从一个 prototype（原型对象）中继承属性和方法。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## prototype 继承\n",
    "所有的 JavaScript 对象都会从一个 prototype（原型对象）中继承属性和方法：\n",
    "\n",
    "- Date 对象从 Date.prototype 继承。\n",
    "- Array 对象从 Array.prototype 继承。\n",
    "- Person 对象从 Person.prototype 继承。\n",
    "\n",
    "所有 JavaScript 中的对象都是位于原型链顶端的 Object 的实例。\n",
    "\n",
    "JavaScript 对象有一个指向一个原型对象的链。当试图访问一个对象的属性时，它不仅仅在该对象上搜寻，还会搜寻该对象的原型，以及该对象的原型的原型，依次层层向上搜索，直到找到一个名字匹配的属性或到达原型链的末尾。\n",
    "\n",
    "Date 对象, Array 对象, 以及 Person 对象从 Object.prototype 继承。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 添加属性和方法\n",
    "有的时候我们想要在所有已经存在的对象添加新的属性或方法。\n",
    "\n",
    "另外，有时候我们想要在对象的构造函数中添加属性或方法。\n",
    "\n",
    "使用 prototype 属性就可以给对象的构造函数添加新的属性："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'English'"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "function Person(first, last, age, eyecolor) {\n",
    "  this.firstName = first;\n",
    "  this.lastName = last;\n",
    "  this.age = age;\n",
    "  this.eyeColor = eyecolor;\n",
    "}\n",
    " \n",
    "Person.prototype.nationality = \"English\";"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "var man = new Person(\"an\",\"en\",20,\"black\",\"chinese\");"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Person { firstName: 'an', lastName: 'en', age: 20, eyeColor: 'black' }\n"
     ]
    }
   ],
   "source": [
    "console.log(man)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "当然我们也可以使用 prototype 属性就可以给对象的构造函数添加新的方法："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Function (anonymous)]"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "function Person(first, last, age, eyecolor) {\n",
    "  this.firstName = first;\n",
    "  this.lastName = last;\n",
    "  this.age = age;\n",
    "  this.eyeColor = eyecolor;\n",
    "}\n",
    " \n",
    "Person.prototype.name = function() {\n",
    "  return this.firstName + \" \" + this.lastName;\n",
    "};"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "var man = new Person(\"an\",\"en\",20,\"black\",\"chinese\");"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'an en'"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "man.name();"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Javascript (Node.js)",
   "language": "javascript",
   "name": "javascript"
  },
  "language_info": {
   "file_extension": ".js",
   "mimetype": "application/javascript",
   "name": "javascript",
   "version": "13.13.0"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "165px"
   },
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
